// #define DONOT_USE_RSEQ
#define _GNU_SOURCE
#include <assert.h>
#include <libapfsds.h>
#include <dbg.h>
#include <dbg/ptest.h>
#include <ddblk_plat.h>
#include <add.h>
#include <htable.h>
#include <nop.h>
#include <queue.h>
#include <stack.h>
#include <rbtree.h>
#include <tlsf.h>
#include <dbg.h>
#ifndef HDEF_LITTLECORE_OFFST
	#warning "undefined LITTLECORE_OFFST"
	#define HDEF_LITTLECORE_OFFST	0
#endif
#define TEST_NR			(1000000)
#define TEST_THREADNR		(HDEF_NATIVE_CPU_NR)
#define WARMUP_THREAD_NR	16
static TLS_INITIAL tid_t mytid;
#include <pthreadalt.h>
static apfsds_t *apfsds;

static word_t volatile test_nr;
SAI NO_UNROLL void *tnop(void *args){
	WRAP_ARGS(ar, NULL);
	word_t ret;
	/* 越大等待时间越短 */
	word_t nr = atm_ld(&test_nr);
	for (;;)
	{
		//printf("args %d\n",args);
		ret = apfsds_sync(apfsds, nop_cnt_cb, ar);
		if(ret >= nr)break;
	}
	return NULL;
}
// int a[next_pow2_clz(1)];

static void set_nop (word_t nop_nr){
	word_t div = (nop_nr/1000);
	

	// printf("%lu, %lu\n", nop_nr, (word_t)next_pow2(nop_nr));
	// assert(next_pow2(nop_nr) >= nop_nr);
	atm_st(&nop_nrs, next_pow2(nop_nr));
	/* 防止临界区太长 */
	if (div == 0) {
		/* 1 : 10TEST_NR , 10 : TEST_NR, 100: TEST_NR*/
		word_t mul = 1;
		if (nop_nr == 1) mul = 10; 
		test_nr = TEST_NR * mul ;
	}
	else{
		test_nr = TEST_NR / div;
	}
						
}

#define FAKE_PRINT(...)
word_t test_nrs_arr[] = {HDEF_NATIVE_CPU_NR};
__PERF_PARALLEL_FUNC_BINDCORE_CUSTOM(tnop , mytid, test_nr, TEST_THREADNR, HDEF_LITTLECORE_OFFST, nop_cnt_reset(), test_nrs_arr, FAKE_PRINT)


/* 这个必须定制好 */

int main(){
	
	/* 绑核 */
	/* BIND_CORE(HDEF_LITTLECORE_OFFST); */
	apfsds = apfsds_create();
	nop_execution = TEST_NR;
	float mop;
	set_nop(1);
	/* dbg_printf("%lu\n", nop_nrs); */
	mop = PERF_PARALLEL_RUN(tnop);
	dbg_printf("%s %u %f\n", "nop", 1, mop);

	set_nop(10);
	/* dbg_printf("%lu\n", nop_nrs); */
	mop = PERF_PARALLEL_RUN(tnop);
	dbg_printf("%s %u %f\n", "nop", 10, mop);

	set_nop(100);
	/* dbg_printf("%lu\n", nop_nrs); */
	mop = PERF_PARALLEL_RUN(tnop);
	dbg_printf("%s %u %f\n", "nop", 100, mop);

	set_nop(1000);
	/* dbg_printf("%lu\n", nop_nrs); */
	mop = PERF_PARALLEL_RUN(tnop);
	dbg_printf("%s %u %f\n", "nop", 1000, mop);

	set_nop(10000);
	/* dbg_printf("%lu\n", nop_nrs); */
	mop = PERF_PARALLEL_RUN(tnop);
	dbg_printf("%s %u %f\n", "nop", 10000, mop);

	set_nop(100000);
	/* dbg_printf("%lu\n", nop_nrs); */
	mop = PERF_PARALLEL_RUN(tnop);
	dbg_printf("%s %u %f\n", "nop", 100000, mop);


	apfsds_destroy(apfsds);
	return 0;
}